<?php

/**
 * This is the model class for table "{{account_token_category}}".
 *
 * The followings are the available columns in table '{{account_token_category}}':
 * @property integer $id
 * @property integer $parentId
 * @property string $name
 * @property string $createTime
 * @property integer $createUserId
 * @property integer $common
 * @property string $updateTime
 * @property integer $updateUserId
 * @property string $childrenCache
 *
 * The followings are the available model relations:
 * @property AccountTokenCategory $parent
 * @property AccountTokenCategory[] $children
 * @property User $createUser
 * @property User $updateUser
 * @property AccountTokenItem[] $accountTokenItems
 */
class AccountTokenCategory extends CActiveRecord {
	/**
	 * Returns the static model of the specified AR class.
	 * @return AccountTokenCategory the static model class
	 */
	public static function model($className = __CLASS__) {
		return parent::model($className);
	}

	/**
	 * @return string the associated database table name
	 */
	public function tableName() {
		return '{{account_token_category}}';
	}
	public function defaultScope() {
		return AccessControl::isAltMode() ? array(
			'condition' => "common<>1",
		) : array();
	}

	/**
	 * @return array validation rules for model attributes.
	 */
	public function rules() {
		// NOTE: you should only define rules for those attributes that
		// will receive user inputs.
		return array(
			array(
				'name',
				'required'
			),
			array(
				'parentId+name',
				'components.db.UniqueMultiColumnValidator',
				'errorAttributes' => array(
					'name'
				),
			),
			array(
				'common',
				'numerical',
				'integerOnly' => true,
			),
			array(
				'name',
				'length',
				'max' => 255
			),
			// The following rule is used by search().
			// Please remove those attributes that should not be searched.
			array(
				'id, parentId, name, createTime, createUserId, updateTime, updateUserId',
				'safe',
				'on' => 'search'
			),
		);
	}

	public function behaviors() {
		return array(
			'AuditableBehavior' => array(
				'class' => 'components.db.AuditableBehavior',
				'attributes' => 'parentId, name, common'
			),
			'AuditStampBehavior' => array(
				'class' => 'components.db.AuditStampBehavior',
			),
		);
	}

	/**
	 * @return array relational rules.
	 */
	public function relations() {
		// NOTE: you may need to adjust the relation name and the related
		// class name for the relations automatically generated below.
		return array(
			'parent' => array(
				self::BELONGS_TO,
				'AccountTokenCategory',
				'parentId'
			),
			'children' => array(
				self::HAS_MANY,
				'AccountTokenCategory',
				'parentId'
			),
			'childrenCount' => array(
				self::STAT,
				'AccountTokenCategory',
				'parentId'
			),
			'createUser' => array(
				self::BELONGS_TO,
				'User',
				'createUserId'
			),
			'updateUser' => array(
				self::BELONGS_TO,
				'User',
				'updateUserId'
			),
			'initial' => array(
				self::HAS_ONE,
				'AccountTokenInitial',
				'categoryId',
				'condition' => 'projectId=' . AccountTokenProject::getGlobalProjectId(),
			)
		//'accountTokenItems' => array(self::HAS_MANY, 'AccountTokenItem', 'categoryId'),
		);
	}

	/**
	 * @return array customized attribute labels (name=>label)
	 */
	public function attributeLabels() {
		return array(
			'id' => 'ID',
			'parentId' => '上级科目',
			'name' => '名称',
			'initialDebit' => '初始借',
			'initialCredit' => '初始贷',
			'common' => '常科目',
			'createTime' => '创建时间',
			'createUserId' => '创建用户',
			'updateTime' => '更新时间',
			'updateUserId' => '更新用户',
		);
	}

	/**
	 * Retrieves a list of models based on the current search/filter conditions.
	 * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
	 */
	public function search() {
		// Warning: Please modify the following code to remove attributes that
		// should not be searched.

		$criteria = new CDbCriteria;

		$criteria->compare('id', $this->id);
		if (!$this->parentId) {
			$criteria->addInCondition('parentId', array(
					null
				));
		} else {
			$criteria->compare('parentId', $this->parentId);
		}
		$criteria->compare('name', $this->name, true);
		$criteria->compare('createTime', $this->createTime, true);
		$criteria->compare('createUserId', $this->createUserId);
		$criteria->compare('updateTime', $this->updateTime, true);
		$criteria->compare('updateUserId', $this->updateUserId);
		$criteria->with = array(
			'childrenCount'
		);

		return new CActiveDataProvider($this, array(
			'criteria' => $criteria,
		));
	}

	public function getDisplayLongName() {
		$name = $this->name;
		$parent = $this;
		while ($parent->parentId) {
			$parent = $parent->parent;
			if ($parent->parentId) {
				$name = $parent->name . '/' . $name;
			}
		}
		return $name;
	}

	public function updateChildrenCache() {
		$childrenCache = array();
		foreach ($this->getRelated('children', true) as $child) {
			$childrenCache[] = $child->id;
			$childrenCache = CMap::mergeArray($childrenCache,
				preg_split('/[\|]+/', $child->childrenCache, -1, PREG_SPLIT_NO_EMPTY));
		}
		if (!empty($childrenCache)) {
			$this->childrenCache = implode('|', $childrenCache);
			$this->save();
		}
		if ($this->parent) {
			$this->parent->updateChildrenCache();
		}
	}

	public function afterSave() {
		parent::afterSave();
		if ($this->getIsNewRecord()) {
			$this->parent->updateChildrenCache();
		}
	}

	public function afterDelete() {
		parent::afterDelete();
		$this->parent->updateChildrenCache();
	}

	public function getLastSum($date, $projectId) {
		$itemModel = AccountTokenItem::model();
		$commandBuilder = Yii::app()->db->getSchema()->getCommandBuilder();
		$criteria = new CDbCriteria();
		$criteria->join = 'INNER JOIN {{account_token}} as token on tokenId=token.id INNER JOIN {{account_token_category}} as category on categoryId=category.id';
		$criteria->compare('tokenDate', '<' . $date);
		$children = preg_split('/[\|]+/', $this->childrenCache, -1, PREG_SPLIT_NO_EMPTY);
		$criteria
			->addInCondition('categoryId', CMap::mergeArray($children, array(
				$this->id
			)));
		if ($projectId) {
			$criteria->compare('projectId', $projectId);
		} else {
			$criteria->addInCondition('projectId', AccountTokenProject::getCompanyProjectIds());
		}
		if ($projectId) {
			$criteria->compare('projectId', $projectId);
		} else {
			$criteria->addInCondition('projectId', AccountTokenProject::getCompanyProjectIds());
		}
		$criteria->select = 'sum(debit) as totalDebit, sum(credit) as totalCredit';
		$command = $commandBuilder->createFindCommand($itemModel->getTableSchema(), $criteria);
		$row = $command->queryRow();
		$criteria = new CDbCriteria();
		$criteria
			->addInCondition('categoryId', CMap::mergeArray($children, array(
				$this->id
			)));

		if ($projectId) {
			$criteria->compare('projectId', $projectId);
		} else {
			$criteria->addInCondition('projectId', AccountTokenProject::getCompanyProjectIds());
		}
		$criteria->select = 'sum(debit) as initialDebit, sum(credit) as initialCredit';
		$command = $commandBuilder
			->createFindCommand(AccountTokenInitial::model()->getTableSchema(), $criteria);
		$rowCategory = $command->queryRow();

		$lastSum = ($rowCategory['initialCredit'] - $rowCategory['initialDebit'])
			+ ($row['totalCredit'] - $row['totalDebit']);
		return round($lastSum, 2);
	}
}
